﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Workflow.Activities;
using System.Workflow.ComponentModel;
using System.ComponentModel;
using System.Diagnostics;
using System.ComponentModel.Design;

// adapted from the *rocking* "Essential Windows Workflow Foundation" book, written by Dharma Shukla and Bob Schmidt, published by Addison-Wesley

namespace TextFlow.Activities
{
    public class TextFlowWhileActivity : CompositeActivity
	{
        public TextFlowWhileActivity()
        {
        }

        public TextFlowWhileActivity( string name ) : base( name )
        {
        }

        public static readonly DependencyProperty ConditionProperty = DependencyProperty.Register(  "Condition",
                                                                                                    typeof( TextFlowCondition ),
                                                                                                    typeof( TextFlowWhileActivity ),
                                                                                                    new PropertyMetadata( DependencyPropertyOptions.Metadata ) );

        [DesignerSerializationVisibility( DesignerSerializationVisibility.Visible )]
        [Browsable( true )]
        public TextFlowCondition Condition
        {
            get { return GetValue( ConditionProperty ) as TextFlowCondition; }
            set { SetValue( ConditionProperty, value ); }
        }

        protected override ActivityExecutionStatus Execute( ActivityExecutionContext aec )
        {
            if ( Condition != null && Condition.Evaluate( this, aec ) )
            {
                ExecuteSequence( aec );

                return ActivityExecutionStatus.Executing;
            }
            else
            {
                return ActivityExecutionStatus.Closed;
            }
        }

        private void OnNextActivity( object sender, ActivityExecutionStatusChangedEventArgs e )
        {
            ActivityExecutionContext aec = sender as ActivityExecutionContext;

            e.Activity.Closed -= OnNextActivity;

            // cleanup inner AEC...

            ActivityExecutionContextManager aecMgr = aec.ExecutionContextManager;

            ActivityExecutionContext dynamicAec = aecMgr.GetExecutionContext( e.Activity );

            aecMgr.CompleteExecutionContext( dynamicAec );

            if (    this.ExecutionStatus == ActivityExecutionStatus.Executing &&
                    this.Condition != null &&
                    this.Condition.Evaluate( this, aec ) )
            {
                ExecuteSequence( aec );
            }
            else
            {
                aec.CloseActivity();
            }
        }

        private void ExecuteSequence( ActivityExecutionContext aec )
        {
            // while semantics require making a copy of child activities for each iteration...

            ActivityExecutionContextManager aecMgr = aec.ExecutionContextManager;

            Debug.Assert( this.EnabledActivities.Count == 1 );

            ActivityExecutionContext newAec = aecMgr.CreateExecutionContext( this.EnabledActivities[ 0 ] );

            SequenceActivity main = newAec.Activity as SequenceActivity;

            main.Closed += OnNextActivity;

            newAec.ExecuteActivity( main );
        }
    }
}
